//
//	MiscClipTextField.m -- a TextField subclass for displaying long string 
//						   values
//		Written and Copyright (c) 1995 by Balazs Pataki. 
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import <appkit/appkit.h>
#import	<misckit/MiscString.h>
#import <objc/objc-runtime.h>

#import "MiscClipTextField.h"
#import "MiscClipTextFieldCell.h"


#define	CLASS_NAME		"MiscClipTextField"
#define	CLASS_VERSION	1
#define CELL_CLASS		[MiscClipTextFieldCell class]


#define DELIMITERS		[delimiters stringValue]


static id	CellClass;	// Class variable of MiscClipTextField



/*
						********************************
						*                              *
						*      MiscClipTextField       *
						*                              *
						********************************
*/

@implementation MiscClipTextField

+ initialize
// Set class version
{
	if (self == objc_lookUpClass(CLASS_NAME))  {
		[self setVersion:CLASS_VERSION];
		CellClass = CELL_CLASS;
	}
	return self;
}

+ setCellClass:classId
{
	CellClass=classId;
	return self;
}


- initFrame:(const NXRect *)rect
// Designated initializer
{
	id	oldCell;
	
	[super initFrame:rect];
										/* Plug in our own cell				*/
	oldCell = [self setCell:[[CellClass alloc] initTextCell:""]];
	[oldCell free];
	
	return self;
}

- setStringValue:(const char*)stringValue
{
	id theCell = [self cell];
	// Change the alignemt to origAlignment because if previously there was
	// a triple-click the cells alignemnt changed to left, which may not have
	// been our original alignment
	[theCell setSelectable:NO];		/* Disable selecting and scrolling		*/
	[theCell setScrollable:NO];
	[theCell setAlignment:origAlignment];
	return [super setStringValue:stringValue];
}

- setAlignment:(int)align
{
	// Save alignment to change it back after a triple-click (triple-click 
	// event changes the cell to display the cell left aligned and we have to
	// take care to undo it) 
	origAlignment = align;
	return self;
}


- resetStringValue:sender
{
	id theCell = [self cell];
	
	[theCell setSelectable:NO];		/* Disable selecting and scrolling		*/
	[theCell setScrollable:NO];
	[theCell setAlignment:origAlignment];
	[[self cell] resetStringValue:sender];
	return self;
}


- setClipEnabled:(BOOL)flag
// Sets whether the next `setStringValue:' message should clip the text or not 
{
	[[self cell] setClipEnabled:flag];
	return self;
}


- setClipOnRight:(BOOL)flag
// If flag is YES clipping happens on the right, otherwise on the left of the 
// string in the cell. 
{
	[[self cell] setClipOnRight:flag];
	return self;
}


- setClipperString:(const char*)aString
// Sets  `aString' as the string that is displayed in place of the clipped part
// of the original string. 
{
	[[self cell] setClipperString:aString];
	return self;
}


- setClipDelimiters:(const char*)delimChars
// Sets  `delimChars' as the delimiters by which the clipping has to happen. 
// If `delimChars' is NULL or an empty string clipping will occur to any 
// character in the string.
{
	[[self cell] setClipDelimiters:delimChars];
	return self;
}

- sizeTo:(NXCoord)width :(NXCoord)height
// Adjusts the current text to the new size and redisplays it
{
	[super sizeTo:width :height];
	[self resetStringValue:self];
	return self;
}


- mouseDown:(NXEvent *)event
// In case of triple-click event displays the full text instead of the clipped
// one and allows selecting and scrolling the string
// NOTE: This trick alters the alignment of the cell and changes it to 
//		 align its text to left and to truncate the text - don't know any
//		 workaround (maybe we should stay with left aligned text only :-(
{ 
	// Handling only triple-click event
	if (event->data.mouse.click == 3) {
		id	theCell  = [self cell];		
		[[self window] disableDisplay];
		[theCell setSelectable:YES];
		[theCell setScrollable:YES];
		[theCell setClipEnabled:NO]; 	/* Turn off clipping for a moment	*/
		[theCell resetStringValue:self];
		[theCell setClipEnabled:YES];	/* ... and turn it back				*/
		[[self window] reenableDisplay];
		[self display];
	}
	return [super mouseDown:event];
}

- (const char*)fullStringValue;	{ return [[self cell] fullStringValue]; }
- clipper					{ return [[self cell] clipper];			}
- delimiters				{ return [[self cell] delimiters];		}
- (BOOL) doesClipOnRight	{ return [[self cell] doesClipOnRight];	}
- (BOOL) isClipEnabled		{ return [[self cell] isClipEnabled];	}

- write:(NXTypedStream *)stream
{
    [super write:stream];
    
    NXWriteType(stream, @encode(int), &origAlignment);
   
    return self;
}


- read:(NXTypedStream *)stream
{
    [super read:stream];
   
	NXReadType(stream, @encode(int), &origAlignment);

	return self;
}

@end


/*
							********************************
							*                              *
							*  MiscClipTextField(IBStuff)  *
							*                              *
							* -- InterfaceBuilder Stuff--  *
							*                              *
							********************************
*/

@implementation MiscClipTextField(IBStuff)

- (const char *)getInspectorClassName
// Return the class name of our inspector.
{
	return "MiscClipTextFieldInspector";
}

@end


/*
							********************************
							*                              *
							*   MiscClipTextField(Test)    *
							*                              *
							* -- Debug and Test Methods -- *
							*                              *
							********************************
*/

@implementation MiscClipTextField(Test)

- changeFont:sender
{
	[[self cell] setFont:[sender selFont]];
	[[self cell] resetStringValue:self];
	return self;
}

@end

